home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / c / cug236.zip / SGREP.C < prev    next >
C/C++ Source or Header  |  1980-01-02  |  21KB  |  830 lines

  1. /*
  2.     HEADER:        CUG000.00;
  3.     TITLE:        SGREP Text Pattern Replacer (McKe86);
  4.     DATE:        05/17/1987;
  5.     DESCRIPTION:    "Is a modified version of the CUG 152 grep program,
  6.             with the added features of string substitution,
  7.             multiple pattern search, case sensitivity, and scanning
  8.             option.";
  9.     VERSION:    1.0;
  10.     KEYWORDS:    Text filter;
  11.     FILENAME:    SGREP.C;
  12.     SEE-ALSO:    SGREP.DOC;
  13.     COMPILERS:    vanilla;
  14.     AUTHORS:    J. McKeon;
  15. */
  16.  
  17. /*
  18.  *
  19.  * The    information  in     this  document     is  subject  to  change
  20.  * without  notice  and     should not be construed as a commitment
  21.  * by Digital Equipment Corporation or by DECUS.
  22.  *
  23.  * Neither Digital Equipment Corporation, DECUS, nor the authors
  24.  * assume any responsibility for the use or reliability of  this
  25.  * document or the described software.
  26.  *
  27.  *    Copyright (C) 1980, DECUS
  28.  *
  29.  * General permission to copy or modify, but not for profit,  is
  30.  * hereby  granted,  provided that the above copyright notice is
  31.  * included and reference made to  the    fact  that  reproduction
  32.  * privileges were granted by DECUS.
  33.  *
  34.  */
  35.  
  36. #include "stdio.h"
  37.  
  38. /*
  39.  * grep.
  40.  *
  41.  * Runs on the Decus compiler or on vms.
  42.  * Converted for BDS compiler (under CP/M-80), 20-Jan-83, by Chris Kern.
  43.  * Converted to IBM PC with CI-C86 C Compiler June 1983 by David N. Smith
  44.  * On vms, define as:
  45.  *    grep :== "$disk:[account]grep"       (native)
  46.  *    grep :== "$disk:[account]grep grep"    (Decus)
  47.  *
  48.  * sgrep.
  49.  *
  50.  * Addition of string substitution capability,
  51.  * multiple pattern search, upper-lower case option, scanning options,
  52.  * and name changed to sgrep, April 1986 by James J. McKeon.
  53.  * Runs on IBM PC or compatibles using ECO C88 compiler.
  54.  *
  55.  * For help type "sgrep ?".  See below for more information.
  56.  *
  57.  * May 1987, William C. Colley, III -- Fixed bug in usage of function fgets()
  58.  * in function compat().  Added several notes about portability to various
  59.  * compilers.  Fixed a glitch in case STAR of function pmatch() that crashed
  60.  * the program when compiled under MSDOS large model.  The glitch occurred
  61.  * when a pointer was (deliberately) run backward past the beginning of an
  62.  * array of char.  The array was exactly on a paragraph boundary, so the
  63.  * pointer decremented from 0x0e5d0000 to 0x0e5dffff instead of to 0x0e5cffff
  64.  * as expected.  A pointer comparison then turned out bogus data and the
  65.  * program went into an infinite loop.  The moral of this story is:  Don't
  66.  * play fast and loose with pointers if you want portability.
  67.  */
  68.  
  69. /*
  70.  * Portability Note:  The AZTEC C compilers handle the binary/text file
  71.  * dichotomy differently from most other compilers.  Uncomment the following
  72.  * pair of #defines if you are running AZTEC C:
  73.  */
  74.  
  75. /*
  76. #define getc(f)        agetc(f)
  77. #define putc(c,f)    aputc(c,f)
  78. */
  79.  
  80. /*
  81.  * Portability Note:  8-bit systems often don't have header file ctype.h.
  82.  * If your system doesn't have it, uncomment the #define NO_CTYPE_H.
  83.  */
  84.  
  85. /*
  86. #define NO_CTYPE_H
  87. */
  88.  
  89. #ifdef    NO_CTYPE_H
  90. int isalpha(), isalnum(), isdigit(), tolower();
  91. #else
  92. #include <ctype.h>
  93. #endif
  94.  
  95. char    *documentation[] = {
  96. "Sgrep searches a file for a given pattern and substitutes a pattern.",
  97. "If no substitution is required, the command sgrep -myn corresponds",
  98. "to grep -n and will match only. Output is to the screen and may be",
  99. "re-directed using \">\" at the DOS level. Execute by",
  100. "  sgrep [flags] pattern-file input-file",
  101. "",
  102. "Flags are single characters preceeded by '-':",
  103. "   -c      Only a count of matching lines is printed",
  104. "   -m      Match patterns only, no substitutions.",
  105. "   -n      Each line is preceeded by its line number",
  106. "   -v      Only print non-matching lines",
  107. "   -y      Upper and lower case match.",
  108. "",
  109. 0 };
  110.  
  111. char    *patdoc[] = {
  112. "Each match pattern is on a separate line followed by its substitute",
  113. "pattern, if any, also on a separate line.",
  114.  
  115. " MATCH PATTERNS",
  116. "The regular_expression defines the pattern to search for.  Upper and",
  117. "lower-case are regarded as different unless -y option is used.",
  118. "x      An ordinary character (not mentioned below) matches that character.",
  119. "'\\'    The backslash quotes any character.  \"\\$\" matches a dollar-sign.",
  120. "'$'    Matches beginning or end of line.",
  121. "'.'    A period matches any character except \"new-line\".",
  122. "':a'   A colon matches a class of characters described by the following",
  123. "':d'     character.  \":a\" matches any alphabetic, \":d\" matches digits,",
  124. "':n'     \":n\" matches alphanumerics, \": \" matches spaces, tabs, and",
  125. "': '     other control characters except new-line.",
  126. "'*'    An expression followed by an asterisk matches zero or more",
  127. "       occurrances of that expression: \"fo*\" matches \"f\", \"fo\"",
  128. "       \"foo\", etc.",
  129. "'+'    An expression followed by a plus sign matches one or more",
  130. "       occurrances of that expression: \"fo+\" matches \"fo\", etc.",
  131. "'-'    An expression followed by a minus sign optionally matches",
  132. "       the expression.",
  133. "'[]'   A string enclosed in square brackets matches any character in",
  134. "       that string, but no others.  If the first character in the",
  135. "       string is a circumflex, the expression matches any character",
  136. "       except \"new-line\" and the characters in the string.  For",
  137. "       example, \"[xyz]\" matches \"xx\" and \"zyx\", while \"[^xyz]\"",
  138. "       matches \"abc\" but not \"axb\".  A range of characters may be",
  139. "       specified by two characters separated by \"-\".  Note that,",
  140. "       [a-z] matches alphabetics, while [z-a] never matches.",
  141. "The concatenation of regular expressions is a regular expression.",
  142.  
  143. " Scanning options:",
  144. "The default scanning option is match all occurences of the pattern.",
  145. "'@'    at the beginning of the pattern, is equivalent to",
  146. "       \"$: *\", meaning match first non-whitespace pattern.",
  147. "'@e'   at the end of a pattern means that if a match is",
  148. "       found (and a substitution made), end all pattern search",
  149. "       on current line.",
  150. "'@r'   at the end of a pattern means that after a match",
  151. "       (and substitution), rescan line until no match occurs.",
  152.  
  153. " SUBSTITUTE PATTERNS ",
  154. "The only control character for substitute patterns is \"?\".",
  155. "Any other character represents itself. Only the characters ? and",
  156. " \\ itself need to be quoted.",
  157.  
  158. "'?n'   where n is a non-zero digit, indicates the position where",
  159. "       the nth wildcard string is to be placed.",
  160. "A wildcard string is any string which is not completely fixed,",
  161. "both as to the characters and number of characters in the string.",
  162. 0};
  163.  
  164. #define LMAX    100
  165. #define PMAX    2000
  166. #define NPATMAX 100
  167.  
  168. #define CHR    1
  169. #define SCOP    2
  170. #define BEOL    3
  171. #define ANY    4
  172. #define CLASS    5
  173. #define NCLASS    6
  174. #define STAR    7
  175. #define PLUS    8
  176. #define MINUS    9
  177. #define ALPHA    10
  178. #define DIGIT    11
  179. #define NALPHA    12
  180. #define PUNCT    13
  181. #define RANGE    14
  182. #define ENDPAT    15
  183. #define lowopt(x) yflag?tolower(x):x
  184.  
  185. int    cflag;
  186. int    mflag;
  187. int    nflag;
  188. int    vflag;
  189. int    yflag;
  190.  
  191. int    debug    =    0;       /* Set for debug code      */
  192.  
  193. char    *pp, *psp;
  194.  
  195. #ifndef vms
  196. char    file_name[81];
  197. #endif
  198.  
  199. char    lbuf[LMAX], slbuf[LMAX];
  200. char    pbuf[PMAX], spbuf[PMAX];
  201. char    * wldstr[19][2];  /* Location of wildcard strings */
  202. int    nws, npat, rescan, nxtln;
  203. char   *mpp[NPATMAX], *mpsp[NPATMAX];  /* Location of patterns */
  204.  
  205. void exit();
  206. /*******************************************************/
  207.  
  208. int main(argc, argv)
  209. int argc;
  210. char *argv[];
  211. {
  212.    register char   *p;
  213.    register int       c;
  214.    FILE           *f;
  215.    void cant(), compat(), grep(), help(), usage();
  216.  
  217.    if (argc <= 1)
  218.       usage("No arguments");
  219.    if (argc == 2 && argv[1][0] == '?' && argv[1][1] == 0) {
  220.       help(documentation);
  221.       help(patdoc);
  222.       return !0;
  223.       }
  224.       p=argv[argc-1];
  225.       if ((f=fopen(p, "r")) == NULL) cant(p);
  226.       p = argv[1];
  227.       if (*p == '-') {
  228.      ++p;
  229.      while (c = *p++) {
  230.         switch(tolower(c)) {
  231.  
  232.         case 'c':
  233.            ++cflag;
  234.            break;
  235.  
  236.         case 'd':
  237.            ++debug;
  238.            break;
  239.  
  240.         case 'm':
  241.            ++mflag;
  242.            break;
  243.  
  244.         case 'n':
  245.            ++nflag;
  246.            break;
  247.  
  248.         case 'v':
  249.